/**
 * @file TcpConnection.cc
 * @brief TCP连接类的实现
 */

#include "TcpConnection.hpp"
#include "EventLoop.hpp"
#include "InetAddress.hpp"
#include <sstream>
#include <iostream>

namespace wd
{
using std::cout;
using std::endl;

// 构造函数：初始化TCP连接
TcpConnection::TcpConnection(int fd, EventLoop * loop,MyLogger &mylogger)
: _sock(fd)
, _sockIO(fd)
, _localAddr(getLocalAddr())
, _peerAddr(getPeerAddr())
, _isShutdownWrite(false)
, _loop(loop)
,_mylogger(mylogger)
{

}

TcpConnection::~TcpConnection()
{
    printf("~TcpConnection()\n");
}

// 获取连接的字符串表示
string TcpConnection::toString() const
{
    std::ostringstream oss;
    oss << "tcp " << _localAddr.ip() << ":" << _localAddr.port()
        << "--> " << _peerAddr.ip() << ":" << _peerAddr.port();
    return oss.str();
}

bool TcpConnection::isClosed() const
{
    char buff[20] = {0};
    return _sockIO.recvPeek(buff, sizeof(buff)) == 0;
}

void TcpConnection::handleNewConnectionCallback()
{
    if(_onConnection) {
        _onConnection(shared_from_this());
    }
}

void TcpConnection::handleMesssageCallback()
{
    if(_onMessage) {
        _onMessage(shared_from_this());
    }
}

void TcpConnection::handleCloseCallback()
{
    if(_onClose) {
        _onClose(shared_from_this());
    }
}

//每一次获取一行数据
string TcpConnection::receive()
{
    char buff[65536] = {0};
    int ret = _sockIO.readline(buff, sizeof(buff));
    return string(buff, ret);
}

int TcpConnection::readPacket(Packet &packet){
    int ret = _sockIO.readPacket(packet);
    cout << "TcpConnection::readPacket recv packet info:" << packet._msg;
    return ret;
}

void TcpConnection::send(const string & msg)
{
    _sockIO.sendn(msg.c_str(), msg.size());
}
    
void TcpConnection::sendInLoop(const string & msg)
{
    if(_loop) {
        _loop->runInLoop(std::bind(&TcpConnection::send, this, msg));
    }
}


void TcpConnection::sendInLoop(const TLV &tlv){
        //char buf[1024] = {0};
        //memset(buf,0,sizeof(buf));
        //memcpy((void*)&buf,(void*)&tlv,tlv.length+8);
        //以下注释用于测试
        //cout <<"buf data:" << buf+8;
        //cout << "type:" << *(int*)buf << endl;
        //cout << "length:" << *(int*)(buf+4) << endl;
        //string response(buf,tlv.length + 8);
        //cout << "response size:" << response.size();
        
        string response = tlv.TLVtoString();       
        sendInLoop(response);
}


void TcpConnection::shutdown()
{
    if(!_isShutdownWrite) {
        _sock.shutdownWrite();
        _isShutdownWrite = true;
    }
}
    
InetAddress TcpConnection::getLocalAddr()
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t len = sizeof(addr);
    int ret = getsockname(_sock.fd(), 
                          (struct sockaddr*)&addr, &len);
    if(ret < 0) {
        perror("getsockname");
    }
    return InetAddress(addr);
}
    
InetAddress TcpConnection::getPeerAddr()
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t len = sizeof(addr);
    int ret = getpeername(_sock.fd(), 
                          (struct sockaddr*)&addr, &len);
    if(ret < 0) {
        perror("getpeername");
    }
    return InetAddress(addr);

}
}//end of namespace wd
